# coding=utf-8
from __future__ import print_function

from sklearn.externals import joblib
from sklearn.model_selection import GridSearchCV

"""
Created on 2016/09/17
By 我曾经被山河大海跨过
http://blog.csdn.net/sb19931201/article/details/52577592
"""
import numpy as np
import pandas as pd
import xgboost as xgb
from sklearn.model_selection import train_test_split, cross_val_score

# from xgboost.sklearn import XGBClassifier
# from sklearn import cross_validation, metrics   #Additional scklearn functions
# from sklearn.grid_search import GridSearchCV   #Perforing grid search
#
# import matplotlib.pylab as plt
# from matplotlib.pylab import rcParams

# 记录程序运行时间
import time
import traceback

# 读入数据
start_time = time.time()
# train = pd.read_excel("data/feature_20180716_0_2_scp_release_20180919_train_small.xlsx")
# tests = pd.read_excel("data/feature_20180716_0_2_scp_release_20180919_predict_small.xlsx")

# train = pd.read_excel("data/feature_20180716_0_2_scp_release_20180919_train.xlsx")
# tests = pd.read_excel("data/feature_20180716_0_2_scp_release_20180919_predict.xlsx")
main_train = pd.read_hdf("data/feature_20180716_0_2_scp_release_20180919_train.h5", "table")
# tests = pd.read_hdf("data/feature_20180716_0_2_scp_release_20180919_predict.h5", "table")
assert isinstance(main_train, pd.DataFrame)
train = main_train[main_train['date'] <= '2018-03-12']
tests = main_train[(main_train['date'] > '2018-05-31') & (main_train['date'] < '2018-07-01')]
assert isinstance(tests, pd.DataFrame)
# train.to_hdf('data/feature_20180716_0_2_scp_release_20180919_train.h5', 'table')
# tests.to_hdf('data/feature_20180716_0_2_scp_release_20180919_predict.h5', 'table')
print(train.drop(['original_quantity', 'date'], axis=1).dtypes.values.tolist())

X = train.drop(['original_quantity', 'date'], axis=1).astype(np.float32)
y = train[['original_quantity']].astype(np.float32)
val_X = tests.drop(['original_quantity', 'date'], axis=1).astype(np.float32)
val_y = tests[['original_quantity']].astype(np.float32)
tests = tests.drop(['date'], axis=1).astype(np.float32)


cost_time = time.time() - start_time
print("load data success! cost time:", cost_time, "(s)")




print("xgboost evaluate and save model successfully!", '\n', "cost time:", cost_time, "(s)")
optimized_GBM = joblib.load('optimized_GBM.pkl')
predict_y = optimized_GBM.predict(val_X)
np_val = np.column_stack((val_X, val_y))
np_val = np.column_stack((np_val, predict_y))

pd_val_col = train.drop(['original_quantity', 'date'], axis=1).dtypes.index.values.tolist()
pd_val_col.append('original_quantity')
pd_val_col.append('prediction')
pd_val = pd.DataFrame(np_val, columns=pd_val_col)
writer = pd.ExcelWriter('result.xlsx')
pd_val.to_excel(writer, 'Sheet1')
writer.save()
# print(predict_y)
# print("------------")
# print(val_y)
# print(optimized_GBM.score(val_X, val_y))
# print(optimized_GBM.score(val_X, predict_y))
print(pd_val)
exit()





start_time = time.time()
params = {
    'booster': 'gbtree',
    'objective': 'multi:softmax',  # 多分类的问题
    # 'num_class': 10,  # 类别数，与 multisoftmax 并用
    'gamma': 0.1,  # 用于控制是否后剪枝的参数,越大越保守，一般0.1、0.2这样子。
    'max_depth': 12,  # 构建树的深度，越大越容易过拟合
    'lambda': 2,  # 控制模型复杂度的权重值的L2正则化项参数，参数越大，模型越不容易过拟合。
    'subsample': 0.7,  # 随机采样训练样本
    'colsample_bytree': 0.7,  # 生成树时进行的列采样
    'min_child_weight': 3,
    # 这个参数默认是 1，是每个叶子里面 h 的和至少是多少，对正负样本不均衡时的 0-1 分类而言
    # ，假设 h 在 0.01 附近，min_child_weight 为 1 意味着叶子节点中最少需要包含 100 个样本。
    # 这个参数非常影响结果，控制叶子节点中二阶导的和的最小值，该参数值越小，越容易 overfitting。
    'silent': 0,  # 设置成1则没有运行信息输出，最好是设置为0.
    'eta': 0.007,  # 如同学习率
    'random_state': 1000,
    'nthread': 7,  # cpu 线程数
    # 'eval_metric': 'auc'
}
plst = list(params.items())
num_rounds = 20
xgb_val = xgb.DMatrix(val_X, label=val_y)
xgb_train = xgb.DMatrix(X, label=y)
xgb_test = xgb.DMatrix(tests)

"""
{"model_parameters":{"max_depth": [4, 6], "n_estimators": [100], "learning_rate": [0.1], "subsample": [0.3, 0.5, 1]}}
"""

# print(xgb_train.feature_names)

watchlist = [(xgb_train, 'original_quantity'), (xgb_val, 'original_quantity')]
# xgb_model = xgb.XGBRegressor()

# scores = cross_val_score(xgb_model, X, y, cv=10)
# print(scores)

cv_params = {'n_estimators': [700, 800, 900, 1000, 1200]}
other_params = {'learning_rate': 0.1, 'n_estimators': 500, 'max_depth': 5, 'min_child_weight': 1, 'seed': 0,
                'subsample': 0.8, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0, 'reg_lambda': 1}
# model_selection()
model = xgb.XGBRegressor(**other_params)
print("=============\n", model.get_params())
print(model.get_xgb_params())
model.set_params(**{'tree_method': 'gpu_hist'})
optimized_GBM = GridSearchCV(estimator=model, param_grid=cv_params, scoring='r2', cv=5,
                             verbose=1, n_jobs=1)


optimized_GBM.fit(X, y)

cost_time = time.time() - start_time
print("xgboost fit finished!", '\n', "cost time:", cost_time, "(s)")

start_time = time.time()
evalute_result = optimized_GBM.grid_scores_
print('每轮迭代运行结果:{0}'.format(evalute_result))
print('参数的最佳取值：{0}'.format(optimized_GBM.best_params_))
print('最佳模型得分:{0}'.format(optimized_GBM.best_score_))
try:
    joblib.dump(optimized_GBM, 'optimized_GBM2.pkl')
except Exception as e:
    traceback.print_exc()

cost_time = time.time() - start_time
print("xgboost evaluate and save model successfully!", '\n', "cost time:", cost_time, "(s)")
optimized_GBM = joblib.load('optimized_GBM.pkl')
predict_y = optimized_GBM.predict(val_X)
print(predict_y)
print("------------")
print(val_y)
print(optimized_GBM.score(val_X, val_y))
print(optimized_GBM.score(val_X, predict_y))
exit()

# xgb_model.fit(X, y)
# predict_y = xgb_model.predict(val_X)
# print(predict_y)
# print("------------")
# print(val_y)
# print(xgb_model.score(val_X, val_y))
# exit()

model = xgb.train(plst, xgb_train, num_rounds,  # watchlist,
                  early_stopping_rounds=100)
model.save_model('./model/xgb.model')
print("best best_ntree_limit", model.best_ntree_limit)
print("跑到这里了model.predict")
preds = model.predict(xgb_test, ntree_limit=model.best_ntree_limit)
np.savetxt('xgb_submission.csv', np.c_[range(1, len(tests) + 1), preds], delimiter=',', header='ImageId,Label',
           comments='', fmt='%d')
cost_time = time.time() - start_time
print("xgboost success!", '\n', "cost time:", cost_time, "(s)")
exit()

# =============================================================================
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                End of test                                                |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# |                                                                           |
# =============================================================================

start_time = time.time()

params = {
    'booster': 'gbtree',
    'objective': 'multi:softmax',  # 多分类的问题
    'num_class': 10,  # 类别数，与 multisoftmax 并用
    'gamma': 0.1,  # 用于控制是否后剪枝的参数,越大越保守，一般0.1、0.2这样子。
    'max_depth': 12,  # 构建树的深度，越大越容易过拟合
    'lambda': 2,  # 控制模型复杂度的权重值的L2正则化项参数，参数越大，模型越不容易过拟合。
    'subsample': 0.7,  # 随机采样训练样本
    'colsample_bytree': 0.7,  # 生成树时进行的列采样
    'min_child_weight': 3,
    # 这个参数默认是 1，是每个叶子里面 h 的和至少是多少，对正负样本不均衡时的 0-1 分类而言
    # ，假设 h 在 0.01 附近，min_child_weight 为 1 意味着叶子节点中最少需要包含 100 个样本。
    # 这个参数非常影响结果，控制叶子节点中二阶导的和的最小值，该参数值越小，越容易 overfitting。
    'silent': 0,  # 设置成1则没有运行信息输出，最好是设置为0.
    'eta': 0.007,  # 如同学习率
    'seed': 1000,
    'nthread': 7,  # cpu 线程数
    # 'eval_metric': 'auc'
}

plst = list(params.items())
num_rounds = 20  # 迭代次数 -.-!!

train_xy, val = train_test_split(train, test_size=0.3, random_state=1)
# random_state is of big influence for val-auc
y = train_xy.label
X = train_xy.drop(['label'], axis=1)
val_y = val.label
val_X = val.drop(['label'], axis=1)

xgb_val = xgb.DMatrix(val_X, label=val_y)
xgb_train = xgb.DMatrix(X, label=y)
xgb_test = xgb.DMatrix(tests)

print(xgb_train.feature_names)

watchlist = [(xgb_train, 'train'), (xgb_val, 'val')]

# training model
# early_stopping_rounds 当设置的迭代次数较大时，early_stopping_rounds 可在一定的迭代次数内准确率没有提升就停止训练
model = xgb.train(plst, xgb_train, num_rounds, watchlist, early_stopping_rounds=100)

model.save_model('./model/xgb.model')  # 用于存储训练出的模型
print("best best_ntree_limit", model.best_ntree_limit)

print("跑到这里了model.predict")
preds = model.predict(xgb_test, ntree_limit=model.best_ntree_limit)

np.savetxt('xgb_submission.csv', np.c_[range(1, len(tests) + 1), preds], delimiter=',', header='ImageId,Label',
           comments='', fmt='%d')

# 输出运行时长
cost_time = time.time() - start_time
print("xgboost success!", '\n', "cost time:", cost_time, "(s)")
